package cn.xuqiudong.rpc.protocol.netty.codec;

import cn.xuqiudong.rpc.common.constants.RequestType;
import cn.xuqiudong.rpc.common.constants.XqdConstants;
import cn.xuqiudong.rpc.common.model.XqdRequest;
import cn.xuqiudong.rpc.common.model.XqdResponse;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.xuqiudong.rpc.cluster.exception.XqdCommonException;
import cn.xuqiudong.rpc.extension.XqdExtensionFactory;
import cn.xuqiudong.rpc.protocol.netty.model.NettyHeader;
import cn.xuqiudong.rpc.protocol.netty.model.NettyProtocolData;
import cn.xuqiudong.rpc.serializer.XqdSerializer;

import java.util.List;

/**
 * 描述: netty中使用的解码器
 * @author Vic.xu
 * @date 2022-02-18 11:15
 */
public class XqdDecoder extends ByteToMessageDecoder {

    /**
     * 通过SpiXqdExtension 获取自适应的序列化方式
     */
    private static XqdSerializer serializer = XqdExtensionFactory.defaultExtendFactory().getAdaptiveXqdExtension(XqdSerializer.class);

    private static Logger logger = LoggerFactory.getLogger(XqdDecoder.class);


    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
       logger.debug("into XqdDecoder.....................");
        if(in.readableBytes()< XqdConstants.HEAD_TOTAL_LEN){
            //消息长度不够，不需要解析
            return;
        }
        //标记一个读取数据的索引，后续用来重置。
        in.markReaderIndex();
        //读取magic
        short magic=in.readShort();
        if(magic != XqdConstants.MAGIC){
            throw new XqdCommonException("Illegal request parameter 'magic'," + magic);
        }
        //序列化类型 预留
        in.readByte();
        //请求类型
        byte reqType=in.readByte();
        //请求消息id
        long requestId=in.readLong();
        //请求数据长度
        int dataLength=in.readInt();
        //可读区域的字节数小于实际数据长度
        if(in.readableBytes() < dataLength){
            in.resetReaderIndex();
            return;
        }
        //读取消息内容
        byte[] content=new byte[dataLength];
        in.readBytes(content);

        //构建header头信息
        NettyHeader header=new NettyHeader(magic, reqType, requestId, dataLength);
        RequestType rt=RequestType.findByCode(reqType);
        switch(rt){
            //请求的数据类型
            case REQUEST:
                XqdRequest request=serializer.deserialize(content, XqdRequest.class);
                NettyProtocolData<XqdRequest> data=new NettyProtocolData<>();
                data.setHeader(header);
                data.setBody(request);
                out.add(data);
                break;
                //相应的数据类型
            case RESPONSE:
                XqdResponse response=serializer.deserialize(content,XqdResponse.class);
                NettyProtocolData<XqdResponse> resProtocol=new NettyProtocolData<>();
                resProtocol.setHeader(header);
                resProtocol.setBody(response);
                out.add(resProtocol);
                break;
            case HEARTBEAT:
            default:
                break;
        }
    }
}
